import { Injectable, BadRequestException } from '@nestjs/common';
import { ChildLimit, SolarTime, Gender, SixtyCycle, EightChar, HeavenStem } from '../utils/bazi-utils';
import { 
  createChildLimit,
  getFullBaziInfo,
  getDecadeFortuneList, 
  getMonthList, 
  getDayList, 
  getHourList,
  getHiddenStems,
  calculateHiddenStemsAndSubStars
} from '../utils/bazi';
import { PatternAnalyzer, BaziSystemData } from '../utils/genju';

/**
 * 八字业务服务 - 极简封装
 * 职责：只做最简单的封装，所有逻辑都在 bazi.ts
 */
@Injectable()
export class BaziService {
  private patternAnalyzer: PatternAnalyzer;
  
  constructor() {
    this.patternAnalyzer = new PatternAnalyzer();
  }
  
  /**
   * 创建八字对象
   * @param solarTime 阳历时间
   * @param gender 性别
   * @param enableZiShiSupport 是否启用早晚子时支持
   * @returns ChildLimit对象
   */
  createChildLimit(solarTime: SolarTime, gender: Gender, enableZiShiSupport: boolean = true): ChildLimit {
    return createChildLimit(solarTime, gender, enableZiShiSupport);
  }

  /**
   * 获取完整八字信息
   * @param solarTime 阳历时间
   * @param gender 性别
   * @param name 姓名（可选）
   * @param longitude 经度（可选）
   * @param latitude 纬度（可选）
   * @param enableZiShiSupport 是否启用早晚子时支持（可选，默认true）
   * @returns 完整八字信息
   */
  getFullBaziInfo(solarTime: SolarTime, gender: Gender, name?: string, longitude?: number, latitude?: number, enableZiShiSupport: boolean = true) {
    return getFullBaziInfo(solarTime, gender, name, longitude, latitude, enableZiShiSupport);
  }

  /**
   * 获取大运列表（包含流年列表）
   * @param solarTime 阳历时间
   * @param gender 性别
   * @returns 大运列表，每个大运包含 children 字段（流年列表）
   */
  getDecadeFortuneList(solarTime: SolarTime, gender: Gender, enableZiShiSupport: boolean = true) {
    const childLimit = this.createChildLimit(solarTime, gender, enableZiShiSupport);
    return getDecadeFortuneList(childLimit);
  }

  /**
   * 获取流月列表
   * @param solarTime 阳历时间
   * @param gender 性别
   * @param decadeIndex 大运索引
   * @param fortuneIndex 流年索引
   * @returns 流月列表
   */
  getMonthList(solarTime: SolarTime, gender: Gender, decadeIndex: number, fortuneIndex: number, enableZiShiSupport: boolean = true) {
    const childLimit = this.createChildLimit(solarTime, gender, enableZiShiSupport);
    return getMonthList(childLimit, decadeIndex, fortuneIndex);
  }

  /**
   * 获取流日列表
   * @param solarTime 阳历时间
   * @param gender 性别
   * @param decadeIndex 大运索引
   * @param fortuneIndex 流年索引
   * @param monthIndex 流月索引
   * @returns 流日列表
   */
  getDayList(solarTime: SolarTime, gender: Gender, decadeIndex: number, fortuneIndex: number, monthIndex: number, enableZiShiSupport: boolean = true) {
    const childLimit = this.createChildLimit(solarTime, gender, enableZiShiSupport);
    return getDayList(childLimit, decadeIndex, fortuneIndex, monthIndex);
  }

  /**
   * 获取流时列表
   * @param solarTime 阳历时间
   * @param gender 性别
   * @param decadeIndex 大运索引
   * @param fortuneIndex 流年索引
   * @param monthIndex 流月索引
   * @param dayIndex 流日索引
   * @returns 流时列表
   */
  getHourList(solarTime: SolarTime, gender: Gender, decadeIndex: number, fortuneIndex: number, monthIndex: number, dayIndex: number, enableZiShiSupport: boolean = true) {
    const childLimit = this.createChildLimit(solarTime, gender, enableZiShiSupport);
    return getHourList(childLimit, decadeIndex, fortuneIndex, monthIndex, dayIndex);
  }

  /**
   * 获取格局分析
   * @param solarTime 阳历时间
   * @param gender 性别
   * @returns 格局分析结果
   */
  getPatternAnalysis(solarTime: SolarTime, gender: Gender, enableZiShiSupport: boolean = true) {
    // 获取完整八字信息
    const fullBaziInfo = this.getFullBaziInfo(solarTime, gender, undefined, undefined, undefined, enableZiShiSupport);
    
    if (!fullBaziInfo) {
      throw new Error('无法获取八字信息');
    }
    
    // 转换为格局分析所需的数据格式
    const baziSystemData: BaziSystemData = {
      year: {
        stem: fullBaziInfo.year.stem,
        branch: fullBaziInfo.year.branch,
        tenStar: fullBaziInfo.year.tenStar,
        zanggan: fullBaziInfo.year.zanggan
      },
      month: {
        stem: fullBaziInfo.month.stem,
        branch: fullBaziInfo.month.branch,
        tenStar: fullBaziInfo.month.tenStar,
        zanggan: fullBaziInfo.month.zanggan
      },
      day: {
        stem: fullBaziInfo.day.stem,
        branch: fullBaziInfo.day.branch,
        tenStar: fullBaziInfo.day.tenStar,
        zanggan: fullBaziInfo.day.zanggan
      },
      hour: {
        stem: fullBaziInfo.hour.stem,
        branch: fullBaziInfo.hour.branch,
        tenStar: fullBaziInfo.hour.tenStar,
        zanggan: fullBaziInfo.hour.zanggan
      }
    };
    
    // 进行格局分析
    const patternResult = this.patternAnalyzer.analyzePatternFromBaziSystem(baziSystemData);
    
    return {
      ...patternResult
    };
  }

  /**
   * 获取当前时间八字信息
   */
  getCurrentTimeBazi(solarTime: SolarTime) {
    const currentTime = new Date();
    
    // 使用现有的getFullBaziInfo方法获取完整八字信息
    const fullBaziInfo = this.getFullBaziInfo(solarTime, Gender.MAN, undefined, undefined, undefined, true);
    
    if (!fullBaziInfo) {
      throw new Error('无法获取当前时间八字信息');
    }
    
    return {
      title: '当前时间八字',
      currentTime: {
        gregorian: `${currentTime.getFullYear()}年${(currentTime.getMonth() + 1).toString().padStart(2, '0')}月${currentTime.getDate().toString().padStart(2, '0')}日 ${currentTime.getHours().toString().padStart(2, '0')}:${currentTime.getMinutes().toString().padStart(2, '0')}`,
        lunar: fullBaziInfo.baseInfo.nongli,
        time: fullBaziInfo.baseInfo.yangli.split(' ')[1] || '00:00',
        timeHour: currentTime.getHours()
      },
      bazi: {
        year: {
          stem: fullBaziInfo.year.stem,
          branch: fullBaziInfo.year.branch,
          ganzhi: fullBaziInfo.year.ganzhi
        },
        month: {
          stem: fullBaziInfo.month.stem,
          branch: fullBaziInfo.month.branch,
          ganzhi: fullBaziInfo.month.ganzhi
        },
        day: {
          stem: fullBaziInfo.day.stem,
          branch: fullBaziInfo.day.branch,
          ganzhi: fullBaziInfo.day.ganzhi
        },
        hour: {
          stem: fullBaziInfo.hour.stem,
          branch: fullBaziInfo.hour.branch,
          ganzhi: fullBaziInfo.hour.ganzhi
        }
      }
    };
  }

  /**
   * 根据八字反推日期
   */
  getDatesFromBazi(sizhu: string) {
    try {
      if (!sizhu?.trim()) {
        throw new BadRequestException('八字字符串不能为空');
      }

      const parts = sizhu.trim().split(/\s+/);
      if (parts.length !== 4) {
        throw new BadRequestException('八字格式错误');
      }

      const [nianZhu, yueZhu, riZhu, shiZhu] = parts;
      const eightChar = new EightChar(
        SixtyCycle.fromName(nianZhu),
        SixtyCycle.fromName(yueZhu),
        SixtyCycle.fromName(riZhu),
        SixtyCycle.fromName(shiZhu)
      );

      const solarTimes = eightChar.getSolarTimes(1801, 2100);
      const dates = solarTimes.slice(0, 50).map(solarTime => {
        const solarDay = solarTime.getSolarDay();
        const lunarDay = solarDay.getLunarDay();
        const lunarMonth = lunarDay.getLunarMonth();
        const lunarYear = lunarMonth.getLunarYear();
        const lunarHour = solarTime.getLunarHour(true);
        const hourName = lunarHour.getSixtyCycle().getEarthBranch().getName() + '时';
        
        // 统一格式：公历和农历都包含年月日时分
        const gregorian = `${solarTime.getYear()}年${solarTime.getMonth().toString().padStart(2, '0')}月${solarTime.getDay().toString().padStart(2, '0')}日 ${solarTime.getHour().toString().padStart(2, '0')}:${solarTime.getMinute().toString().padStart(2, '0')}`;
        // 农历格式：具体年份 + 干支年 + 月份名称（已包含"月"）+ 日期名称 + "日" + 时辰
        const lunarYearName = lunarYear.getSixtyCycle().getName();
        const lunarMonthName = lunarMonth.getName();
        const lunarDayName = lunarDay.getName();
        const lunarYearNumber = lunarYear.getYear();
        const lunar = `${lunarYearNumber}年${lunarYearName}年${lunarMonthName}${lunarDayName}日 ${hourName}`;
        
        return { gregorian, lunar };
      });

      return { sizhu, dates, count: dates.length };

    } catch (error) {
      throw new BadRequestException(`八字反推失败: ${error.message}`);
    }
  }

  /**
   * 从八字字符串构建 BaziSystemData
   * @param bazi 八字字符串（8个字符：年干年支月干月支日干日支时干时支）
   * @returns BaziSystemData
   */
  buildBaziSystemDataFromString(bazi: string): BaziSystemData {
    if (!bazi || bazi.length !== 8) {
      throw new BadRequestException('八字字符串必须是8个字符');
    }

    // 解析八字字符串：年干年支月干月支日干日支时干时支
    const yearCycle = SixtyCycle.fromName(bazi[0] + bazi[1]);
    const monthCycle = SixtyCycle.fromName(bazi[2] + bazi[3]);
    const dayCycle = SixtyCycle.fromName(bazi[4] + bazi[5]);
    const hourCycle = SixtyCycle.fromName(bazi[6] + bazi[7]);

    const dayMaster = dayCycle.getHeavenStem();

    // 使用工具类构建完整数据
    const buildPillarData = (cycle: SixtyCycle) => {
      const stem = cycle.getHeavenStem();
      const branch = cycle.getEarthBranch();
      const hiddenStems = getHiddenStems(branch);
      const zanggan = calculateHiddenStemsAndSubStars(dayMaster, hiddenStems);
      
      return {
        stem: stem.getName(),
        branch: branch.getName(),
        tenStar: dayMaster.getTenStar(stem).getName(),
        zanggan: zanggan
      };
    };

    return {
      year: buildPillarData(yearCycle),
      month: buildPillarData(monthCycle),
      day: {
        ...buildPillarData(dayCycle),
        tenStar: '日元'
      },
      hour: buildPillarData(hourCycle)
    };
  }
}